package com.workflow.workflowproject.serviceImpl;

import ch.qos.logback.core.util.StringCollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.util.StringUtil;
import com.mybatisflex.core.util.UpdateEntity;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import com.workflow.workflowproject.entity.FlowField;
import com.workflow.workflowproject.entity.FlowForm;
import com.workflow.workflowproject.entity.FlowInfo;
import com.workflow.workflowproject.entity.table.FlowFieldTableDef;
import com.workflow.workflowproject.entity.table.FlowFormTableDef;
import com.workflow.workflowproject.mapper.FlowFieldMapper;
import com.workflow.workflowproject.mapper.FlowFormMapper;
import com.workflow.workflowproject.mapper.FlowInfoMapper;
import com.workflow.workflowproject.pojo.ProcessModel;
import com.workflow.workflowproject.pojo.lowflow.FieldModel;
import com.workflow.workflowproject.service.FlowFormService;
import com.workflow.workflowproject.tools.Result.Result;
import com.workflow.workflowproject.until.ElementToVant;
import com.workflow.workflowproject.until.FieldEnum;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.util.ArrayListWrapper;
import org.apache.velocity.util.StringUtils;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.common.engine.impl.util.io.StringStreamSource;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.ProcessEngines;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.repository.Deployment;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.beans.Transient;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class FlowFormServiceImpl extends ServiceImpl<FlowFormMapper, FlowForm> implements FlowFormService {

    @Autowired
    private FlowFieldMapper flowFieldMapper;
    @Autowired
    private FlowInfoMapper flowInfoMapper;
    @Autowired
    private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
    /**
     * 添加流程表单版本信息
     *
     * @param
     * @return
     */
    @Override
    public Result addFlowForm(FlowForm flowForm) throws Exception {
        flowForm.setId(null);
        flowForm.setState(0);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分ss秒");
        flowForm.setVersionName(simpleDateFormat.format(new Date()));
        if(this.getMapper().insert(flowForm) == 0){
            return Result.fail("添加流程版本信息失败");
        }
        return Result.ok(flowForm);
    }
    /**
     * 修改流程表单版本信息
     *
     * @param
     * @return
     */
    @Override
    @Transactional
    public Result updateFlowForm(String id,Integer type,FlowForm flowForm) throws Exception {
        //如果流程
        if(!ObjectUtils.isEmpty(flowForm.getProcessModel())){
            //流程数据
            String json = JSONObject.toJSONString(flowForm.getProcessModel());
            json = json.replaceAll("\"@type\":\"java.util.LinkedHashMap\",","");
            flowForm.setLowFlowJson(json);
            //流程对象
            BpmnModel bpmnModel = flowForm.getProcessModel().toBpmnModel();
            byte[] xmlBytes = new BpmnXMLConverter().convertToXML(bpmnModel);
            String bpmnXml = new String(xmlBytes);
            flowForm.setFlowBpmnXml(bpmnXml);
        }
        List<JSONObject> pcFieldList = flowForm.getPcFormJson();
        List<JSONObject> mvFieldList = ElementToVant.elementToVant(pcFieldList);
        flowForm.setMvFormJson(mvFieldList);
        //如果是PC端修改
        flowForm.setId(id);
        this.getMapper().update(flowForm);
        for(JSONObject jsonObject : pcFieldList){
            //查询是否有组件
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.where(FlowFieldTableDef.FLOW_FIELD.FIELD_NAME.eq(jsonObject.getString("field")));
            FlowField flowField = flowFieldMapper.selectOneByQuery(queryWrapper);
            //如果没有组件，则进行添加该组件
            if(ObjectUtils.isEmpty(flowField)){
                flowField = new FlowField();
                flowField.setFormId(flowForm.getId());
                flowField.setFieldName(jsonObject.getString("field"));
                flowField.setTitle(jsonObject.getString("title"));
                flowFieldMapper.insert(flowField);
            }else{
                flowField.setFormId(flowForm.getId());
                flowField.setFieldName(jsonObject.getString("field"));
                flowField.setTitle(jsonObject.getString("title"));
                flowFieldMapper.update(flowField);
            }
        }
        return Result.ok(flowForm);
    }
    /**
     * 通过id查询流程表单版本
     *
     * @param
     * @return
     */
    @Override
    public Result getFlowFormById(Long id) throws Exception {
        FlowForm flowForm = this.getMapper().selectOneById(id);
        return Result.ok(flowForm);
    }
    /**
     * 通过流程信息id查询流程表单版本
     *
     * @param
     * @return
     */
    @Override
    public Result getFlowFormByFlowInfoId(Integer flowInfoId) throws Exception {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.where(FlowFormTableDef.FLOW_FORM.FLOW_INFO_ID.eq(flowInfoId));
        queryWrapper.orderBy(FlowFormTableDef.FLOW_FORM.CREATE_TIME.desc());
        List<FlowForm> flowFormList = this.getMapper().selectListByQuery(queryWrapper);
        return Result.ok(flowFormList,flowFormList.size());
    }
    /**
     * 通过流程信息id查询上线的表单
     *
     * @param
     * @return
     */
    @Override
    public Result processOnlineForm(Integer flowInfoId) throws Exception {
        FlowInfo flowInfo = flowInfoMapper.selectOneById(flowInfoId);
        FlowForm flowForm = this.getMapper().selectOneById(flowInfo.getCurrentVersion());
        return Result.ok(flowForm);
    }

    /**
     * 通过lowflow查询字段
     *
     * @param
     * @return
     */
    @Override
    public Result getFlowFieldByFlowInfoId(String flowFormId) throws Exception {
        //查询之前的数据
        FlowForm flowForm = this.getMapper().selectOneById(flowFormId);
        List<JSONObject> pcFieldList = flowForm.getPcFormJson();
        List<FieldModel> fieldModelLists = new ArrayList<>();
        for(JSONObject jsonObject : pcFieldList){
            String isInType = FieldEnum.isLowFormType(jsonObject.getString("type"));
            if(!isInType.equals("NO")){
                FieldModel fieldModel = new FieldModel();
                fieldModel.setId(jsonObject.getString("field"));
                fieldModel.setType("formItem");
                fieldModel.setLabel(jsonObject.getString("title"));
                fieldModel.setName(isInType);
                fieldModel.setValue(null);
                fieldModel.setReadonly(false);
                fieldModel.setRequired(true);
                fieldModel.setHidden(false);
                JSONObject propObject = new JSONObject();
                propObject.put("disabled",false);
                propObject.put("placeholder",jsonObject.getString("title"));
                propObject.put("multiple",false);
                propObject.put("options",jsonObject.getJSONArray("options"));
                fieldModel.setProps(propObject);
                fieldModelLists.add(fieldModel);
            }
        }
        return Result.ok(fieldModelLists);
    }
    /**
     * 流程上线
     *
     * @param
     * @return
     */
    @Override
    @Transactional
    public Result processOnline(FlowForm flowForm) throws Exception {
        FlowForm flowFormOne = this.getMapper().selectOneById(flowForm.getId());
        FlowInfo flowInfo = flowInfoMapper.selectOneById(flowFormOne.getFlowInfoId());
        //查询是否有启用的流程
        if(StringUtil.isNotBlank(flowInfo.getCurrentVersion())){
            //如果有已经启用的流程
            FlowForm flowFormOnline = this.getMapper().selectOneById(flowInfo.getCurrentVersion());
            flowFormOnline.setState(0);
            this.getMapper().update(flowFormOnline);
        }
        //部署到flowable中
        RepositoryService repositoryService = processEngine.getRepositoryService();
        Deployment deploy = repositoryService.createDeployment()
                .name(flowInfo.getName())
                .key(flowFormOne.getId())
                .addString(flowFormOne.getId() + ".bpmn20.xml", flowFormOne.getFlowBpmnXml())
                .deploy();
        log.info("部署流程 name:"+deploy.getName()+" key "+deploy.getKey() + " deploy "+deploy);
        BpmnXMLConverter bpmnXMLConverter = new BpmnXMLConverter();
        BpmnModel bpmnModel = bpmnXMLConverter.convertToBpmnModel(new StringStreamSource(flowFormOne.getFlowBpmnXml()), false, false);
        flowFormOne.setFlowId(bpmnModel.getProcesses().get(0).getId());
        this.getMapper().update(flowFormOne);
        flowInfo.setCurrentVersion(flowFormOne.getId());
        flowInfoMapper.update(flowInfo);
        flowFormOne.setState(1);
        this.getMapper().update(flowFormOne);
        return Result.ok();
    }
    /**
     * 下线流程
     *
     * @param
     * @return
     */
    @Override
    @Transactional
    public Result offlineProcess(FlowForm flowForm) throws Exception {
        FlowForm flowFormOne = this.getMapper().selectOneById(flowForm.getId());
        flowFormOne.setState(0);
        this.getMapper().update(flowFormOne);
        FlowInfo flowInfo = UpdateEntity.of(FlowInfo.class, flowFormOne.getFlowInfoId());
        flowInfo.setCurrentVersion(null);
        flowInfoMapper.update(flowInfo);
        return Result.ok();
    }

}
